package com.wyvoid.forum.dao.hibernate;

import com.wyvoid.core.persistent.Pagination;
import com.wyvoid.core.persistent.hibernate.HibernateDAO;
import com.wyvoid.core.persistent.hibernate.HibernatePage;
import com.wyvoid.forum.domain.Topic;
import com.wyvoid.forum.domain.Post;
import com.wyvoid.forum.dao.ITopicDAO;
import com.wyvoid.forum.Constant;
import com.wyvoid.forum.web.search.SearchBean;
import com.sohospace.lucene.analysis.xanalyzer.XQueryAnalyzer;
import org.springframework.dao.DataAccessException;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.hibernate.search.FullTextQuery;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.search.*;
import org.apache.lucene.index.Term;
import org.apache.lucene.document.DateTools;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;

import java.util.List;
import java.util.Map;
import java.util.Calendar;

/**
 * 帮助信息Hibernate数据处理实现
 *
 * @author wyvoid
 * @version $Revision: 1.21 $ $Date: 2006/07/28 17:04:32 $
 * @link www.wyvoid.com
 */
public class TopicDAO extends HibernateDAO<Topic> implements ITopicDAO {

    /**
     * 取得制定论坛的贴子
     *
     * @param forumId    论坛编号
     * @param categoryId 类别编号 (-1,表示不设定CategoryId)
     * @param status     贴子状态 (1 精华, 0 全部)
     * @param pagination 分页参数
     * @return QueryResult 帖子集合
     * @throws DataAccessException
     */
    public HibernatePage<Topic> findTopics(int forumId, int categoryId, Map orderMap, int status, Pagination pagination) {
        /*DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Topic.class);
     detachedCriteria.add(Restrictions.eq("forumId", forumId));
     if (status != 0) {
         detachedCriteria.add(Restrictions.eq("status", status));
     }
     if (categoryId != -1) {
         detachedCriteria.add(Restrictions.eq("categoryId", categoryId));
     }
     detachedCriteria.add(Restrictions.not(Restrictions.eq("isDelete", new Integer(1))));
     orderMap.put("lastPostTime", "desc");
     return super.findItemsByCriteria(detachedCriteria, orderMap, pagination);*/
        return null;
    }

    /**
     * 检索帖子
     *
     * @param forumId    论坛编号
     * @param type       检索类型
     * @param keyword    检索关键字
     * @param timePoint  时间点 当timePoint为""时，不进行时间设定
     * @param way        时间方向
     * @param orderMap   排序信息
     * @param pagination
     * @return
     */
    public HibernatePage<Topic> searchTopics(int forumId, String type, String keyword, String timePoint, String way, Map orderMap, Pagination pagination) {

        return null;/*DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Topic.class);
            if (forumId != 0) {
                detachedCriteria.add(Restrictions.eq("forumId", new Integer(forumId)));
            }
            detachedCriteria.add(Restrictions.like(type, "%" + keyword + "%"));
            if (!("".equals(timePoint))) {
                if ("after".equals(way)) {
                    detachedCriteria.add(Restrictions.gt("dateCreated", timePoint));
                } else {
                    detachedCriteria.add(Restrictions.lt("dateCreated", timePoint));
                }
            }
            detachedCriteria.add(Restrictions.not(Restrictions.eq("isDelete", new Integer(1))));
            return super.findItemsByCriteria(detachedCriteria, orderMap, pagination);*/

    }

    /**
     * 取得制定论坛的贴子
     *
     * @param forumId    论坛编号
     * @param orderMap   排序数组
     * @param pagination 分页对象
     * @return QueryResult 论坛贴子列表
     */
    public HibernatePage<Topic> findTopics(final long forumId, Map orderMap, final Pagination pagination) {
        /*DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Topic.class);
        detachedCriteria.add(Restrictions.eq("forumId", forumId));
        detachedCriteria.add(Restrictions.not(Restrictions.eq("isDelete", new Integer(1))));
        return super.findItemsByCriteria(detachedCriteria, orderMap, pagination);*/
        String hql = "from Topic where forumId=? and status>=0 order by toped desc,lastPost.createTime desc";
        return doQuery(hql, true, pagination, forumId);
    }


    /**
     * 根据主题论坛版块编号删除主题
     *
     * @param forumId 主题编号
     */
    public void deleteTopicByForum(int forumId) {

        super.executeHsql("delete from Topic where forumId='" + forumId + "'");


    }

    /**
     * 更新贴子浏览次数
     *
     * @param topicId 贴子编号
     */
    public void updateTopicViews(int topicId) {
        super.executeHsql("update Topic set views=views+1 where id='" + topicId + "'");

    }

    /**
     * 更新主题是否被删除状态
     *
     * @param topicId  主题编号
     * @param isDelete 是否被删除
     *                 isDelete 1 将主题丢弃到垃圾箱，0 主题状态正常
     */
    public void updateTopicIsDelete(int topicId, int isDelete) {
        super.executeHsql("update Topic set isDelete='" + isDelete + "' where id='" + topicId + "'");

    }

    /**
     * 更新主题是否被置顶
     *
     * @param topicId 主题编号
     * @param isTop   是否被置顶
     *                isTop 1 置顶，0 主题状态正常
     */
    public void updateTopicIsTop(int topicId, int isTop) {

        super.executeHsql("update Topic set isTop='" + isTop + "' where id='" + topicId + "'");

    }

    public Topic getNextTopic(long tid, Topic curTopic) {
        String hql = "from Topic where createTime<? and forumId=? order by createTime desc";
        List<Topic> topics = doQueryLimitList(hql, true, 1, curTopic.getCreateTime(), curTopic.getForumId());
        if (topics.size() > 0) {
            return topics.get(0);
        } else {
            return null;
        }
    }

    public Topic getLastTopic(long tid, Topic curTopic) {
        String hql = "from Topic where createTime>? and forumId=? order by createTime";
        List<Topic> topics = doQueryLimitList(hql, true, 1, curTopic.getCreateTime(), curTopic.getForumId());
        if (topics.size() > 0) {
            return topics.get(0);
        } else {
            return null;
        }
    }

    /**
     * 更新主题状态
     *
     * @param topicId 主题编号
     * @param status  是否被置顶
     *                status 1 精华贴，2 被锁定的贴子
     */
    public void updateTopicStatus(int topicId, int status) {
        super.executeHsql("update Topic set status='" + status + "' where id='" + topicId + "'");

    }


    /**
     * 将主题丢到垃圾箱
     *
     * @param topicId 主题编号
     */
    public void trashTopic(int topicId) {
        super.executeHsql("update Topic set isDelete=1 where id='" + topicId + "'");
    }

    /**
     * 取得主题总数
     *
     * @return
     */
    public long countTopic() {
        return doQueryCount("select count(t.id) from Topic as t where t.status>" + Constant.Topic.STATUS_DEL);
    }

    /**
     * 根据ForumId统计主题总数
     *
     * @param forumId
     * @return
     */
    public long countTopic(int forumId) {
        return doQueryCount("select count(t.id) from Topic as t where t.forumId='" + forumId + "' and t.status>" + Constant.Topic.STATUS_DEL);
    }

    /**
     * 根据论坛编号查找制定数目的主题
     *
     * @param forumId 论坛编号
     * @param dataNum 结果数
     * @return List 主题列表
     */
    public List findTopic(int forumId, int dataNum) {
        String hql = getFromHql() + " where forumId=? order by lastPostTime desc";
        return super.doQueryLimitList(hql, true, dataNum, forumId);
    }


    /**
     * 移动主题
     *
     * @param topicId 主题列表
     * @param forumId 论坛编号
     */
    public void moveTopic(int topicId, int forumId) {
        super.executeHsql("update Topic set forumId='" + forumId + "' where id=" + topicId);
    }

    public void indexAll() {
        FullTextSession fullTextSession = Search.createFullTextSession(this.getSession());
        List<Topic> topics = getHibernateTemplate().loadAll(Topic.class);
        for (Topic topic : topics) {
            fullTextSession.index(topic);
        }
    }

    public HibernatePage<Topic> searchTopics(SearchBean searchBean, Pagination pagination) {
        FullTextSession textSession = Search.createFullTextSession(this.getSession());
        BooleanQuery comboQuery = new BooleanQuery();

        if (StringUtils.isNotBlank(searchBean.getKey())) {
            String keyWord = searchBean.getKey();
            if (keyWord.indexOf(" ") > 0) {
                String[] s = keyWord.split(" ");
                keyWord = "";
                int x = 0;
                for (String s1 : s) {
                    s1 = "title:" + s1 + "";
                    keyWord += s1;
                    if (x < s.length - 1) keyWord += " and ";
                    x++;
                }
            }

            QueryParser parser = new QueryParser("title", new XQueryAnalyzer());
            org.apache.lucene.search.Query luceneQuery;
            try {
                luceneQuery = parser.parse(keyWord);
                comboQuery.add(luceneQuery, BooleanClause.Occur.MUST);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

        if (searchBean.getBeforeTimes() != 0) {
            Calendar now = Calendar.getInstance();
            Calendar lower = (Calendar) now.clone();
            lower.add(Calendar.SECOND, -searchBean.getBeforeTimes());
            if (searchBean.getBefore() == 1) {
                now = (Calendar) lower.clone();
                lower.setTimeInMillis(0);
            }
            RangeQuery rangeQuery = new RangeQuery(new Term("createTime", DateFormatUtils.format(lower.getTime(), "yyyyMMdd")), new Term("createTime", DateFormatUtils.format(now.getTime(), "yyyyMMdd")), true);
            comboQuery.add(rangeQuery, BooleanClause.Occur.MUST);
        }
        if (!ArrayUtils.isEmpty(searchBean.getForumIds()) && !ArrayUtils.contains(searchBean.getForumIds(), 0)) {
            for (long fid : searchBean.getForumIds()) {
                TermQuery termQuery = new TermQuery(new Term("forumId", fid + ""));
                comboQuery.add(termQuery, BooleanClause.Occur.MUST);
            }
        }

        if (searchBean.getSearchFilter() == 1) {
            TermQuery termQuery = new TermQuery(new Term("status", "1"));
            comboQuery.add(termQuery, BooleanClause.Occur.MUST);
        } else if (searchBean.getSearchFilter() == 2) {
            TermQuery termQuery = new TermQuery(new Term("toped", "true"));
            comboQuery.add(termQuery, BooleanClause.Occur.MUST);
        }

        Sort sort;
        boolean desc = StringUtils.equals(searchBean.getAscdesc(), "desc");
        if (StringUtils.equals(searchBean.getOrderby(), "lastPost")) {
            sort = new Sort(new SortField("createTime", desc));
        } else {
            sort = new Sort(new SortField("lastPost.createTime", desc));
        }


        FullTextQuery fullTextQuery = textSession.createFullTextQuery(comboQuery, Topic.class);
        fullTextQuery.setSort(sort);
        int total = fullTextQuery.getResultSize();
        List<Post> result = fullTextQuery.list();
        return new HibernatePage(result, total, pagination.getPageNumber(), pagination.getPageSize());
    }

    public HibernatePage<Topic> searchTopics2(SearchBean searchBean, Pagination pagination) {
        String hql = "from Topic where 1=1 ";


        if (!ArrayUtils.isEmpty(searchBean.getForumIds())) {
            long fid = searchBean.getForumIds()[0];
            hql += " and forumId = " + fid + " ";
        }

        int beforeTimes = searchBean.getBeforeTimes();
        if (beforeTimes > 0) {
            hql += " and createTime>? ";
        }

        int searchFilter = searchBean.getSearchFilter();
        if (searchFilter == 1) {
            hql += " and status=1 ";
        } else if (searchFilter == 2) {
            hql += " and toped=true";
        }

        hql += " order by toped desc,";

        String orderBy = searchBean.getOrderby();
        if (StringUtils.equals(orderBy, "dateline")) {
            hql += " createTime ";
        } else if (StringUtils.equals(orderBy, "replies")) {
            hql += " postCount ";
        } else if (StringUtils.equals(orderBy, "views")) {
            hql += " viewCount ";
        }else{
            hql+=" lastPost.createTime ";
        }

        if (StringUtils.equalsIgnoreCase("asc", searchBean.getAscdesc())) {
            hql += " asc ";
        } else {
            hql += " desc ";
        }
        if (beforeTimes > 0) {
            Calendar last = Calendar.getInstance();
            last.add(Calendar.SECOND, -beforeTimes);
            return new HibernatePage<Topic>(hql, this.getHibernateTemplate().getSessionFactory().getCurrentSession(), true, pagination.getPageNumber(), pagination.getPageSize(), last.getTime());
        } else {
            return new HibernatePage<Topic>(hql, this.getHibernateTemplate().getSessionFactory().getCurrentSession(), true, pagination.getPageNumber(), pagination.getPageSize());
        }
    }
}